home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac 1993 September / September 93.iso / Archives / Applications / Assorted Programs / PCB Cad / IO.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-10  |  24.9 KB  |  892 lines  |  [TEXT/UNIX]

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. /*#include <malloc.h>*/
  5. #include <ctype.h>
  6. #include "cell.h"
  7.  
  8. /* board dimensions */
  9. extern int Nrows;
  10. extern int Ncols;
  11.  
  12. extern int InitBoardDone; /* sanity check */
  13.  
  14. /* memory usage */
  15. extern long Ltotal; /* for board */
  16. extern long Itotal; /* for dist */
  17. extern long Ctotal; /* for dir */
  18.  
  19. /*
  20. ** the following types of input lines are legal (spaces and tabs can separate
  21. ** tokens, and case is not significant):
  22. **
  23. **  1) a blank line (ignored)
  24. **  2) ';' followed by anything (ignored)
  25. **     use semicolon to insert comments.
  26. **  3) DIMENSION (row,column)
  27. **     this defines the number of rows and columns on the board, and must be
  28. **     given before any of the lines below. note that the user sees the board
  29. **     coordinate space as being 1-based, but internally it is 0-based.
  30. **  4) HOLE (row,column)
  31. **     this defines a hole location.
  32. **  5) CONNECT thing AND thing
  33. **     this declares that two holes are to be electrically connected. a thing
  34. **     can be (row,column), or name1.name2, where name1 is the name of a
  35. **     CHIPAT-defined chip, and name2 is the name of one of its pins, or a
  36. **     number, giving the pin number of the named chip. you can use '='
  37. **     instead of 'AND' if you want.
  38. **  6) PRIORITY CONNECT thing AND thing
  39. **     same as above, except the order of connections will be preserved. the
  40. **     autorouter is free to reorder the non-PRIORITY CONNECTs, and in fact
  41. **     reorders them shortest first. if there are PRIORITY CONNECTs, they will
  42. **     all be routed before non-PRIORITY CONNECTs.
  43. **  7) INCLUDE filename
  44. **     this causes the input to be temporarily taken from the given filename.
  45. **     when the given filename is completely processed (EOF encountered),
  46. **     control returns to the current file. INCLUDE statements may be nested
  47. **     (they may occur inside the given filename). complete and partial
  48. **     pathnames can be used (C:\TTL.INC, ..\TTL.INC, \TTL.INC, FOO\TTL.INC).
  49. **  8) CHIP TYPE=type PINS=number HORIZONTAL=number VERTICAL=number
  50. **     this declares a chip type, which can be used to place chips on the
  51. **     board (see CHIPAT, below), but does not itself place anything on the
  52. **     board. TYPE gives the name that will be used in later CHIPAT
  53. **     statements. PINS declares the number of pins. HORIZONTAL gives the
  54. **     number of 50-mil units separating adjacent pins (along the long side of
  55. **     the chip). and VERTICAL gives the number of 50-mil units separating
  56. **     pins across from each other (across the skinny width of the chip).
  57. **     standard values for HORIZONTAL and VERTICAL are 2 and 6, respectively.
  58. **     all CHIP type names must be unique.
  59. **  9) number=name
  60. **     this declares a pin name for the chip that is currently being defined.
  61. **     this statement must follow a CHIP statement. pins not defined will have
  62. **     no name, but you can still refer to them by number. each pin on a chip
  63. **     can be named at most once.
  64. ** 10) name=number
  65. **     same as above.
  66. ** 11) CHIPAT (row,column) NAME=name TYPE=type ORIENTATION=orientation
  67. **     this defines an instance of a chip, and places the appropriate holes on
  68. **     the board. (row,column) is the location of pin 1. NAME defines the name
  69. **     to be used in following CONNECT statements. TYPE declares the
  70. **     CHIPAT-defined type of the chip. ORIENTATION can have the values
  71. **     NORMAL, UP, DOWN, and UPSIDEDOWN. all CHIPAT names must be unique.
  72. **
  73. **      NORMAL           UP           DOWN        UPSIDEDOWN
  74. **
  75. **       6 5 4          +---+         +---+          3 2 1
  76. **     +-*-*-*-+      4 *   * 3     1 * | * 6      +-*-*-*-+
  77. **     |  ->   |      5 * ^ * 2     2 * v * 5      |   <-  |
  78. **     +-*-*-*-+      6 * | * 1     3 *   * 4      +-*-*-*-+
  79. **       1 2 3          +---+         +---+          4 5 6
  80. **
  81. **     usually the highest-numbered pin (pin N) is Vcc (power) and the pin
  82. **     farthest from it (pin N/2) is GND (ground).
  83. */
  84.  
  85. /* chip orientations (rotations) */
  86. #define ORIENT_NORMAL        1
  87. #define ORIENT_UP        2
  88. #define ORIENT_DOWN        3
  89. #define ORIENT_UPSIDEDOWN    4
  90.  
  91. /* input token types */
  92. #define TOK_EOF        1    /* end of file, no more tokens        */
  93. #define TOK_NEWLINE    2    /* end of line                */
  94. #define TOK_NUMBER    3    /* number (digits)            */
  95. #define TOK_HOLE    4    /* "HOLE"                */
  96. #define TOK_ROWCOLUMN    5    /* "(row,column)"            */
  97. #define TOK_CONNECT    6    /* "CONNECT"                */
  98. #define TOK_EQUAL    7    /* "="                    */
  99. #define TOK_AND        8    /* "AND"                */
  100. #define TOK_ALPHANUM    9    /* name (letters, digits, ':','.','\')    */
  101. #define TOK_CHIP    10    /* "CHIP"                */
  102. #define TOK_NAME    11    /* "NAME"                */
  103. #define TOK_PINS    12    /* "PINS"                */
  104. #define TOK_HORIZONTAL    13    /* "HORIZONTAL"                */
  105. #define TOK_VERTICAL    14    /* "VERTICAL"                */
  106. #define TOK_INCLUDE    15    /* "INCLUDE"                */
  107. #define TOK_CHIPAT    16    /* "CHIPAT"                */
  108. #define TOK_TYPE    17    /* "TYPE"                */
  109. #define TOK_ORIENTATION    18    /* "ORIENTATION"            */
  110. #define TOK_NORMAL    19    /* "NORMAL"                */
  111. #define TOK_UP        20    /* "UP"                    */
  112. #define TOK_DOWN    21    /* "DOWN"                */
  113. #define TOK_UPSIDEDOWN    22    /* "UPSIDEDOWN"                */
  114. #define TOK_DIMENSION    23    /* "DIMENSION"                */
  115. #define TOK_PRIORITY    24    /* "PRIORITY"                */
  116.  
  117. struct reserved { /* reserved word input tokens */
  118.     char *tokenname;
  119.     int tokenvalue;
  120.     };
  121.  
  122. static struct reserved tokenmatch[] = { /* reserved word table */
  123.   { "HOLE",       TOK_HOLE       },  { "CONNECT",     TOK_CONNECT     },
  124.   { "AND",        TOK_AND        },  { "CHIP",        TOK_CHIP        },
  125.   { "NAME",       TOK_NAME       },  { "PINS",        TOK_PINS        },
  126.   { "HORIZONTAL", TOK_HORIZONTAL },  { "VERTICAL",    TOK_VERTICAL    },
  127.   { "INCLUDE",    TOK_INCLUDE    },  { "CHIPAT",      TOK_CHIPAT      },
  128.   { "TYPE",       TOK_TYPE       },  { "ORIENTATION", TOK_ORIENTATION },
  129.   { "NORMAL",     TOK_NORMAL     },  { "UP",          TOK_UP          },
  130.   { "DOWN",       TOK_DOWN       },  { "UPSIDEDOWN",  TOK_UPSIDEDOWN  },
  131.   { "DIMENSION",  TOK_DIMENSION  },  { "PRIORITY",    TOK_PRIORITY    }
  132.  };
  133.  
  134. #define MAXTOK    80    /* maximum token length (including null) */
  135.  
  136. static int numres = sizeof(tokenmatch) / sizeof(tokenmatch[0]);
  137. static char token[MAXTOK]; /* the current token is formed here */
  138.  
  139. struct pinassign { /* for assigning names to pins */
  140.     int            index;
  141.     char far        *name;
  142.     struct pinassign far    *next;
  143.     };
  144.  
  145. struct template { /* for "CHIP" declarations */
  146.     char far        *type;
  147.     int            pins;
  148.     int            horizontal;
  149.     int            vertical;
  150.     struct pinassign far    *pinlist;
  151.     struct template far    *next;
  152.     };
  153.  
  154. struct instance { /* for "CHIPAT" definitions */
  155.     int            row;
  156.     int            column;
  157.     char far        *name;
  158.     struct template far    *type;
  159.     int            orientation;
  160.     struct instance far    *next;
  161.     };
  162.  
  163. static struct template far *chip = NULL; /* list of CHIPs */
  164. static struct instance far *chipat = NULL; /* list of CHIPATs */
  165.  
  166. extern void InitBoard( void );
  167. extern long GetCell( int, int, int );
  168. extern void SetCell( int, int, int, long );
  169. extern void InitWork( void );
  170. extern void SetWork( int, int, char far *, int, int, char far *, int );
  171. extern void SortWork( void );
  172. extern void Nomem( void );
  173.  
  174. void Initialize( FILE * );
  175. static void initfile( FILE * );
  176. static void initchip( struct instance far * );
  177. static void locate( char *, int *, int * );
  178. static int gettoken( FILE * );
  179. static char far *fcopy( char * );
  180. static int same( char far *, char far * );
  181. void Report( FILE * );
  182.  
  183. void Initialize ( fin ) /* get hole coordinates and connections */
  184.     FILE *fin;
  185.     {
  186.     printf( "enter Initialize()\n" );
  187.     InitWork(); /* clear work list */
  188.     initfile( fin ); /* read input file(s) */
  189.     SortWork(); /* arrange to do shortest ones first */
  190.     printf( "  %ld bytes used for board\n", Ltotal );
  191.     printf( "  %ld bytes used for dist\n", Itotal );
  192.     printf( "  %ld bytes used for dir\n", Ctotal );
  193.     printf( "leave Initialize()\n" );
  194.     }
  195.  
  196. /* some useful macros (common code sequences) */
  197.  
  198. #define SkipRest    { while ((tok = gettoken( fin )) != TOK_EOF \
  199.                 && tok != TOK_NEWLINE) ; }
  200.  
  201. #define SkipTokRest    { while (tok != TOK_EOF && tok != TOK_NEWLINE) \
  202.                 tok = gettoken( fin ); } \
  203.             continue;
  204.  
  205. #define CheckInit    { if (!InitBoardDone) { \
  206.                 printf( "error: need dimensions first\n" ); \
  207.                 SkipRest; \
  208.                 continue; } }
  209.  
  210. void strupr ( char *ptr)
  211. {
  212.    while ( *ptr ) {
  213.       *ptr = (char) toupper ( *ptr );
  214.       ptr++;
  215.    }
  216. }
  217.  
  218. static void initfile ( fin ) /* read and process input file(s) */
  219.     FILE *fin;
  220.     {
  221.     int tok, r1, c1, r2, c2, i;
  222.     char far *p;
  223.     char far *n1;
  224.     char far *n2;
  225.     long cell;
  226.     struct template far *p1;
  227.     struct pinassign far *p2;
  228.     struct pinassign far *p22;
  229.     struct instance far *p3;
  230.     FILE *fnew;
  231.  
  232.     while ((tok = gettoken( fin )) != TOK_EOF) {
  233.         if (tok == TOK_DIMENSION) {
  234.             if (InitBoardDone) { /* can only do it once */
  235.                 printf( "error: redundant dimensions\n" );
  236.                 SkipRest;
  237.                 continue;
  238.                 }
  239.             if ((tok = gettoken( fin )) != TOK_ROWCOLUMN) {
  240.                 printf( "expect (row,column)\n" );
  241.                 SkipTokRest;
  242.                 }
  243.             sscanf( token, "(%d,%d)", &Nrows, &Ncols );
  244.             if (Nrows <= 0 || Ncols <= 0)
  245.                 printf( "dimension error\n" );
  246.             else /* allocate memory for data structures */
  247.                 InitBoard();
  248.             }
  249.         else if (tok == TOK_HOLE) {
  250.             CheckInit; /* must get dimensions first */
  251.             if ((tok = gettoken( fin )) != TOK_ROWCOLUMN) {
  252.                 printf( "expect (row,column)\n" );
  253.                 SkipTokRest;
  254.                 }
  255.             sscanf( token, "(%d,%d)", &r1, &c1 );
  256.             if (r1 <= 0 || r1 > Nrows || c1 <= 0 || c1 > Ncols)
  257.                 printf( "out of range\n" );
  258.             else { /* position the hole on the board */
  259.                 /* should check for neighbor holes (error) */
  260.                 SetCell( r1-1, c1-1, TOP, HOLE );
  261.                 SetCell( r1-1, c1-1, BOTTOM, HOLE );
  262.                 }
  263.             }
  264.         else if (tok == TOK_CONNECT) {
  265.             CheckInit; /* must get dimensions first */
  266.             if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
  267.                 sscanf( token, "(%d,%d)", &r1, &c1 );
  268.             else if (tok == TOK_ALPHANUM)
  269.                 locate( token, &r1, &c1 );
  270.             else {
  271.                 printf( "expect (row,column) or name\n" );
  272.                 SkipTokRest;
  273.                 }
  274.             n1 = fcopy( token );
  275.             if ((tok = gettoken( fin )) != TOK_EQUAL
  276.                 && tok != TOK_AND) {
  277.                 printf( "expect = or AND\n" );
  278.                 SkipTokRest;
  279.                 }
  280.             if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
  281.                 sscanf( token, "(%d,%d)", &r2, &c2 );
  282.             else if (tok == TOK_ALPHANUM)
  283.                 locate( token, &r2, &c2 );
  284.             else {
  285.                 printf( "expect (row,column) or name\n" );
  286.                 SkipTokRest;
  287.                 }
  288.             n2 = fcopy( token );
  289.             if (r1 <= 0 || r1 > Nrows || r2 <= 0 || r2 > Nrows
  290.                 || c1 <= 0 || c1 > Ncols
  291.                 || c2 <= 0 || c2 > Ncols) {
  292.                 printf( "out of range\n" );
  293.                 _ffree( n1 );
  294.                 _ffree( n2 );
  295.                 }
  296.             else {
  297.                 cell = GetCell( r1-1, c1-1, TOP );
  298.                 if (!(cell & HOLE)) {
  299.                     printf( "error: no source hole\n" );
  300.                     _ffree( n1 );
  301.                     _ffree( n2 );
  302.                     SkipRest;
  303.                     continue;
  304.                     }
  305.                 cell = GetCell( r2-1, c2-1, TOP );
  306.                 if (!(cell & HOLE)) {
  307.                     printf( "error: no target hole\n" );
  308.                     _ffree( n1 );
  309.                     _ffree( n2 );
  310.                     SkipRest;
  311.                     continue;
  312.                     }
  313.                 SetWork( r1-1, c1-1, n1, r2-1, c2-1, n2, 0 );
  314.                 }
  315.             }
  316.         else if (tok == TOK_PRIORITY) {
  317.             CheckInit; /* must get dimensions first */
  318.             if ((tok = gettoken( fin )) != TOK_CONNECT) {
  319.                 printf( "expect CONNECT\n" );
  320.                 SkipTokRest;
  321.                 }
  322.             if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
  323.                 sscanf( token, "(%d,%d)", &r1, &c1 );
  324.             else if (tok == TOK_ALPHANUM)
  325.                 locate( token, &r1, &c1 );
  326.             else {
  327.                 printf( "expect (row,column) or name\n" );
  328.                 SkipTokRest;
  329.                 }
  330.             n1 = fcopy( token );
  331.             if ((tok = gettoken( fin )) != TOK_EQUAL
  332.                 && tok != TOK_AND) {
  333.                 printf( "expect = or AND\n" );
  334.                 SkipTokRest;
  335.                 }
  336.             if ((tok = gettoken( fin )) == TOK_ROWCOLUMN)
  337.                 sscanf( token, "(%d,%d)", &r2, &c2 );
  338.             else if (tok == TOK_ALPHANUM)
  339.                 locate( token, &r2, &c2 );
  340.             else {
  341.                 printf( "expect (row,column) or name\n" );
  342.                 SkipTokRest;
  343.                 }
  344.             n2 = fcopy( token );
  345.             if (r1 <= 0 || r1 > Nrows || r2 <= 0 || r2 > Nrows
  346.                 || c1 <= 0 || c1 > Ncols
  347.                 || c2 <= 0 || c2 > Ncols) {
  348.                 printf( "out of range\n" );
  349.                 _ffree( n1 );
  350.                 _ffree( n2 );
  351.                 }
  352.             else {
  353.                 cell = GetCell( r1-1, c1-1, TOP );
  354.                 if (!(cell & HOLE)) {
  355.                     printf( "error: no source hole\n" );
  356.                     _ffree( n1 );
  357.                     _ffree( n2 );
  358.                     SkipRest;
  359.                     continue;
  360.                     }
  361.                 cell = GetCell( r2-1, c2-1, TOP );
  362.                 if (!(cell & HOLE)) {
  363.                     printf( "error: no target hole\n" );
  364.                     _ffree( n1 );
  365.                     _ffree( n2 );
  366.                     SkipRest;
  367.                     continue;
  368.                     }
  369.                 SetWork( r1-1, c1-1, n1, r2-1, c2-1, n2, 1 );
  370.                 }
  371.             }
  372.         else if (tok == TOK_INCLUDE) {
  373.             CheckInit; /* must get dimensions first */
  374.             if ((tok = gettoken( fin )) != TOK_ALPHANUM) {
  375.                 printf( "expect name for INCLUDE\n" );
  376.                 SkipTokRest;
  377.                 }
  378.             if (!(fnew = fopen( token, "r" ))) {
  379.                 printf( "can't open INCLUDE file %s\n",
  380.                     token );
  381.                 SkipRest;
  382.                 continue;
  383.                 }
  384.             if ((tok = gettoken( fin )) != TOK_EOF
  385.                 && tok != TOK_NEWLINE) {
  386.                 printf( "extra chars on INCLUDE line\n" );
  387.                 SkipRest;
  388.                 }
  389.             initfile( fnew ); /* recurse */
  390.             if (fclose( fnew ))
  391.                 printf( "error closing INCLUDE file\n" );
  392.             continue; /* already ate the NEWLINE, if any */
  393.             }
  394.         else if (tok == TOK_CHIP) {
  395.             CheckInit; /* must get dimensions first */
  396.             if ((tok = gettoken( fin )) != TOK_TYPE
  397.                 || (tok = gettoken( fin )) != TOK_EQUAL
  398.                 || (tok = gettoken( fin )) != TOK_ALPHANUM) {
  399.                 printf( "expect TYPE=type\n" );
  400.                 SkipTokRest;
  401.                 }
  402.             if (!(p1 = (struct template far *)
  403.                 _fmalloc( sizeof(struct template) )))
  404.                 Nomem();
  405.             p1->type = fcopy( token );
  406.             if ((tok = gettoken( fin )) != TOK_PINS
  407.                 || (tok = gettoken( fin )) != TOK_EQUAL
  408.                 || (tok = gettoken( fin )) != TOK_NUMBER) {
  409.                 printf( "expect PINS=number\n" );
  410.                 _ffree( p1->type );
  411.                 _ffree( p1 );
  412.                 SkipTokRest;
  413.                 }
  414.             sscanf( token, "%d", &i );
  415.             p1->pins = i;
  416.             if ((p1->pins = i) < 0 || (i & 1))
  417.                 printf( "PINS negative or odd\n" );
  418.             if ((tok = gettoken( fin )) != TOK_HORIZONTAL
  419.                 || (tok = gettoken( fin )) != TOK_EQUAL
  420.                 || (tok = gettoken( fin )) != TOK_NUMBER) {
  421.                 printf( "expect HORIZONTAL=number\n" );
  422.                 _ffree( p1->type );
  423.                 _ffree( p1 );
  424.                 SkipTokRest;
  425.                 }
  426.             sscanf( token, "%d", &i );
  427.             if ((p1->horizontal = i) <= 0)
  428.                 printf( "HORIZONTAL nonpositive\n" );
  429.             if ((tok = gettoken( fin )) != TOK_VERTICAL
  430.                 || (tok = gettoken( fin )) != TOK_EQUAL
  431.                 || (tok = gettoken( fin )) != TOK_NUMBER) {
  432.                 printf( "expect VERTICAL=number\n" );
  433.                 _ffree( p1->type );
  434.                 _ffree( p1 );
  435.                 SkipTokRest;
  436.                 }
  437.             sscanf( token, "%d", &i );
  438.             if ((p1->vertical = i) < 0)
  439.                 printf( "VERTICAL nonpositive\n" );
  440.             p1->pinlist = NULL;
  441.             p1->next = chip;
  442.             chip = p1;
  443.             }
  444.         else if (tok == TOK_NUMBER) {
  445.             CheckInit; /* must get dimensions first */
  446.             if (!chip) {
  447.                 printf( "no template\n" );
  448.                 SkipRest;
  449.                 continue;
  450.                 }
  451.             sscanf( token, "%d", &i );
  452.             if ((tok = gettoken( fin )) != TOK_EQUAL
  453.                 || (tok = gettoken( fin )) != TOK_ALPHANUM) {
  454.                 printf( "expect number=name\n" );
  455.                 SkipTokRest;
  456.                 }
  457.             if (!(p2 = (struct pinassign far *)
  458.                 _fmalloc( sizeof(struct pinassign) )))
  459.                 Nomem();
  460.             p2->name = fcopy( token );
  461.             p2->index = i;
  462.             /* check uniqueness of name and index */
  463.             for (p22 = chip->pinlist; p22; p22 = p22->next)
  464.                 if (p22->index == i
  465.                     || same( p22->name, p )) {
  466.                     printf( "warning: repeated pin\n" );
  467.                     break;
  468.                     }
  469.             p2->next = chip->pinlist;
  470.             chip->pinlist = p2;
  471.             }
  472.         else if (tok == TOK_ALPHANUM) {
  473.             CheckInit; /* must get dimensions first */
  474.             if (!chip) {
  475.                 printf( "no template\n" );
  476.                 SkipRest;
  477.                 continue;
  478.                 }
  479.             p = fcopy( token );
  480.             if ((tok = gettoken( fin )) != TOK_EQUAL
  481.                 || (tok = gettoken( fin )) != TOK_NUMBER) {
  482.                 printf( "expect name=number\n" );
  483.                 _ffree( p );
  484.                 SkipTokRest;
  485.                 }
  486.             sscanf( token, "%d", &i );
  487.             if (!(p2 = (struct pinassign far *)
  488.                 _fmalloc( sizeof(struct pinassign) )))
  489.                 Nomem();
  490.             p2->name = p;
  491.             p2->index = i;
  492.             /* check uniqueness of name and index */
  493.             for (p22 = chip->pinlist; p22; p22 = p22->next)
  494.                 if (p22->index == i
  495.                     || same( p22->name, p )) {
  496.                     printf( "warning: repeated pin\n" );
  497.                     break;
  498.                     }
  499.             p2->next = chip->pinlist;
  500.             chip->pinlist = p2;
  501.             }
  502.         else if (tok == TOK_CHIPAT) {
  503.             CheckInit; /* must get dimensions first */
  504.             if ((tok = gettoken( fin )) != TOK_ROWCOLUMN) {
  505.                 printf( "expect (row,column)\n" );
  506.                 SkipTokRest;
  507.                 }
  508.             sscanf( token, "(%d,%d)", &r1, &c1 );
  509.             if ((tok = gettoken( fin )) != TOK_NAME
  510.                 || (tok = gettoken( fin )) != TOK_EQUAL
  511.                 || (tok = gettoken( fin )) != TOK_ALPHANUM) {
  512.                 printf( "expect NAME=name\n" );
  513.                 SkipTokRest;
  514.                 }
  515.             if (!(p3 = (struct instance far *)
  516.                 _fmalloc( sizeof(struct instance) )))
  517.                 Nomem();
  518.             p3->name = fcopy( token );
  519.             p3->row = r1;
  520.             p3->column = c1;
  521.             if ((tok = gettoken( fin )) != TOK_TYPE
  522.                 || (tok = gettoken( fin )) != TOK_EQUAL
  523.                 || (tok = gettoken( fin )) != TOK_ALPHANUM) {
  524.                 printf( "expect TYPE=type\n" );
  525.                 _ffree( p3->name );
  526.                 _ffree( p3 );
  527.                 SkipTokRest;
  528.                 }
  529.             for (p3->type = chip; p3->type;
  530.                 p3->type = p3->type->next)
  531.                 if (same( token, p3->type->type ))
  532.                     break;
  533.             if (!(p3->type)) {
  534.                 printf( "couldn't find chip type\n" );
  535.                 _ffree( p3->name );
  536.                 _ffree( p3 );
  537.                 SkipTokRest;
  538.                 }
  539.             if ((tok = gettoken( fin )) != TOK_ORIENTATION
  540.                 || (tok = gettoken( fin )) != TOK_EQUAL
  541.                 || ((tok = gettoken( fin )) != TOK_NORMAL
  542.                 && tok != TOK_UP && tok != TOK_DOWN
  543.                 && tok != TOK_UPSIDEDOWN)) {
  544.                 printf( "expect ORIENTATION=orientation\n" );
  545.                 _ffree( p3->name );
  546.                 _ffree( p3 );
  547.                 SkipTokRest;
  548.                 }
  549.             switch (tok) {
  550.             case TOK_NORMAL:
  551.                 p3->orientation = ORIENT_NORMAL;    break;
  552.             case TOK_UP:
  553.                 p3->orientation = ORIENT_UP;        break;
  554.             case TOK_DOWN:
  555.                 p3->orientation = ORIENT_DOWN;        break;
  556.             case TOK_UPSIDEDOWN:
  557.                 p3->orientation = ORIENT_UPSIDEDOWN;    break;
  558.             default:
  559.                 printf( "internal error\n" );
  560.                 exit( -1 );
  561.                 break;
  562.                 }
  563.             p3->next = chipat;
  564.             chipat = p3;
  565.             initchip( p3 );
  566.             }
  567.         else if (tok == TOK_NEWLINE)
  568.             continue;
  569.         else /* something unexpected */
  570.             printf( "syntax error: unexpected input\n" );
  571.         if ((tok = gettoken( fin )) != TOK_EOF && tok != TOK_NEWLINE) {
  572.             printf( "syntax error: expected end of line\n" );
  573.             SkipRest;
  574.             }
  575.         }
  576.     }
  577.  
  578. static void initchip ( p ) /* initialize a chip definition (create holes) */
  579.     struct instance far *p;
  580.     {
  581.     int r, c, pin;
  582.     struct template far *t;
  583.  
  584.     pin = 1;
  585.     r = p->row;
  586.     c = p->column;
  587.     t = p->type;
  588.     /* should check for neighboring holes (warning if so) */
  589.     switch (p->orientation) {
  590.     case ORIENT_NORMAL:
  591.         while (pin <= t->pins / 2) {
  592.             SetCell( r-1, c-1, TOP, HOLE );
  593.             SetCell( r-1, c-1, BOTTOM, HOLE );
  594.             pin++;
  595.             c += t->horizontal;
  596.             }
  597.         c -= t->horizontal;
  598.         r += t->vertical;
  599.         while (pin <= t->pins) {
  600.             SetCell( r-1, c-1, TOP, HOLE );
  601.             SetCell( r-1, c-1, BOTTOM, HOLE );
  602.             pin++;
  603.             c -= t->horizontal;
  604.             }
  605.         break;
  606.     case ORIENT_UP:
  607.         while (pin <= t->pins / 2) {
  608.             SetCell( r-1, c-1, TOP, HOLE );
  609.             SetCell( r-1, c-1, BOTTOM, HOLE );
  610.             pin++;
  611.             r += t->horizontal;
  612.             }
  613.         r -= t->horizontal;
  614.         c -= t->vertical;
  615.         while (pin <= t->pins) {
  616.             SetCell( r-1, c-1, TOP, HOLE );
  617.             SetCell( r-1, c-1, BOTTOM, HOLE );
  618.             pin++;
  619.             r -= t->horizontal;
  620.             }
  621.         break;
  622.     case ORIENT_DOWN:
  623.         while (pin <= t->pins / 2) {
  624.             SetCell( r-1, c-1, TOP, HOLE );
  625.             SetCell( r-1, c-1, BOTTOM, HOLE );
  626.             pin++;
  627.             r -= t->horizontal;
  628.             }
  629.         r += t->horizontal;
  630.         c += t->vertical;
  631.         while (pin <= t->pins) {
  632.             SetCell( r-1, c-1, TOP, HOLE );
  633.             SetCell( r-1, c-1, BOTTOM, HOLE );
  634.             pin++;
  635.             r += t->horizontal;
  636.             }
  637.         break;
  638.     case ORIENT_UPSIDEDOWN:
  639.         while (pin <= t->pins / 2) {
  640.             SetCell( r-1, c-1, TOP, HOLE );
  641.             SetCell( r-1, c-1, BOTTOM, HOLE );
  642.             pin++;
  643.             c -= t->horizontal;
  644.             }
  645.         c += t->horizontal;
  646.         r -= t->vertical;
  647.         while (pin <= t->pins) {
  648.             SetCell( r-1, c-1, TOP, HOLE );
  649.             SetCell( r-1, c-1, BOTTOM, HOLE );
  650.             pin++;
  651.             c += t->horizontal;
  652.             }
  653.         break;
  654.     default:
  655.         printf( "internal error: unexpected orientation\n" );
  656.         exit( -1 );
  657.         break;
  658.         }
  659.     }
  660.  
  661. static void locate ( p, r, c ) /* find location of name1.{name2,number} */
  662.     char *p;
  663.     int *r, *c;
  664.     {
  665.     char *q;
  666.     int i;
  667.     struct instance far *s;
  668.     struct pinassign far *t;
  669.  
  670.     if (!(q = strchr( p, '.' ))) {
  671.         printf( "expect name1.{name2,number}\n" );
  672.         return;
  673.         }
  674.     *q++ = 0; /* separate into two parts & point at second part */
  675.     for (s = chipat; s; s = s->next) /* find proper chip */
  676.         if (same( p, s->name ))
  677.             break;
  678.     if (!s || !(s->type)) {
  679.         printf( "can't find chip or chip type\n" );
  680.         return;
  681.         }
  682.     if (isdigit( *q )) { /* get pin number */
  683.         i = atoi( q );
  684.         if (i <= 0 || i > s->type->pins) {
  685.             printf( "pin out of range\n" );
  686.             return;
  687.             }
  688.         }
  689.     else { /* get index of named pin via the template */
  690.         for (t = s->type->pinlist; t; t = t->next)
  691.             if (same( q, t->name ))
  692.                 break;
  693.         if (!t) {
  694.             printf( "can't find pin\n" );
  695.             return;
  696.             }
  697.         i = t->index;
  698.         }
  699.     *r = s->row;
  700.     *c = s->column;
  701.     switch (s->orientation) {
  702.     case ORIENT_NORMAL:
  703.         if (i <= s->type->pins / 2)
  704.             *c += (i-1) * s->type->horizontal;
  705.         else {
  706.             *r += s->type->vertical;
  707.             *c += (s->type->pins - i) * s->type->horizontal;
  708.             }
  709.         break;
  710.     case ORIENT_UP:
  711.         if (i <= s->type->pins / 2)
  712.             *r += (i-1) * s->type->horizontal;
  713.         else {
  714.             *c -= s->type->vertical;
  715.             *r += (s->type->pins - i) * s->type->horizontal;
  716.             }
  717.         break;
  718.     case ORIENT_DOWN:
  719.         if (i <= s->type->pins / 2)
  720.             *r -= (i-1) * s->type->horizontal;
  721.         else {
  722.             *c += s->type->vertical;
  723.             *r -= (s->type->pins - i) * s->type->horizontal;
  724.             }
  725.         break;
  726.     case ORIENT_UPSIDEDOWN:
  727.         if (i <= s->type->pins / 2)
  728.             *c -= (i-1) * s->type->horizontal;
  729.         else {
  730.             *r -= s->type->vertical;
  731.             *c -= (s->type->pins - i) * s->type->horizontal;
  732.             }
  733.         break;
  734.     default:
  735.         printf( "internal error: unexpected orientation\n" );
  736.         exit( -1 );
  737.         break;
  738.         }
  739.     *--q = '.'; /* put back the separator */
  740.     }
  741.  
  742. static int gettoken ( fin ) /* get next token into token[], return value */
  743.     FILE *fin;
  744.     {
  745.     int ch, i;
  746.  
  747.     /* burn whitespace */
  748.     while ((ch = getc( fin )) == ' ' || ch == '\t') ;
  749.     if (ch == EOF)
  750.         return( TOK_EOF );
  751.     else if (ch == '\n')
  752.         return( TOK_NEWLINE );
  753.     else if (ch == ';') { /* comment; burn to end of line */
  754.         while ((ch = getc( fin )) != EOF && ch != '\n') ;
  755.         return( (ch == '\n') ? TOK_NEWLINE : TOK_EOF );
  756.         }
  757.     else if (ch == '=')
  758.         return( TOK_EQUAL );
  759.     else if (isdigit( ch )) { /* a number; move it to the buffer */
  760.         i = 0;
  761.         do {
  762.             if (i < MAXTOK-1)
  763.                 token[i++] = (char)ch;
  764.             ch = getc( fin );
  765.             } while (isdigit( ch ));
  766.         token[i] = 0;
  767.         if (ch != EOF)
  768.             ungetc( ch, fin );
  769.         return( TOK_NUMBER );
  770.         }
  771.     else if (isalpha( ch ) || ch == '.' || ch == '\\') {
  772.         /* a name; move it to the buffer */
  773.         i = 0;
  774.         do {
  775.             if (i < MAXTOK-1)
  776.                 token[i++] = (char)ch;
  777.             ch = getc( fin );
  778.             } while (isalnum( ch ) || ch == ':' || ch == '.'
  779.                 || ch == '\\');
  780.         token[i] = 0;
  781.         if (ch != EOF)
  782.             ungetc( ch, fin );
  783.         /* try to identify it as a reserved word */
  784.         strupr( token );
  785.         for (i = 0; i < numres; i++) /* search table */
  786.             if (!stricmp( tokenmatch[i].tokenname, token ))
  787.                 return( tokenmatch[i].tokenvalue );
  788.         /* it's not a reserved word; just return it */
  789.         /*strupr( token );*/
  790.         return( TOK_ALPHANUM );
  791.         }
  792.     else if (ch == '(') { /* "(row,column)", move it to the buffer */
  793.         token[0] = (char)ch;
  794.         i = 1;
  795.         while ((ch = getc( fin )) == ' ' || ch == '\t') ;
  796.         if (!isdigit( ch )) {
  797.             printf( "syntax error: expected digit\n" );
  798.             exit( -1 );
  799.             }
  800.         do {
  801.             if (i < MAXTOK-1)
  802.                 token[i++] = (char)ch;
  803.             ch = getc( fin );
  804.             } while (isdigit( ch ));
  805.         while (ch == ' ' || ch == '\t')
  806.             ch = getc( fin );
  807.         if (ch != ',') {
  808.             printf( "syntax error: expected comma\n" );
  809.             exit( -1 );
  810.             }
  811.         if (i < MAXTOK-1)
  812.             token[i++] = (char)ch;
  813.         while ((ch = getc( fin )) == ' ' || ch == '\t') ;
  814.         if (!isdigit( ch )) {
  815.             printf( "syntax error: expected digit\n" );
  816.             exit( -1 );
  817.             }
  818.         do {
  819.             if (i < MAXTOK-1)
  820.                 token[i++] = (char)ch;
  821.             ch = getc( fin );
  822.             } while (isdigit( ch ));
  823.         while (ch == ' ' || ch == '\t')
  824.             ch = getc( fin );
  825.         if (ch != ')') {
  826.             printf( "syntax error: expected right paren\n" );
  827.             exit( -1 );
  828.             }
  829.         if (i < MAXTOK-1)
  830.             token[i++] = (char)ch;
  831.         token[i] = 0;
  832.         return( TOK_ROWCOLUMN );
  833.         }
  834.     else {
  835.         printf( "syntax error: unrecognized token\n" );
  836.         exit( -1 );
  837.         }
  838.     }
  839.  
  840. static char far *fcopy ( p ) /* return ptr to far string copy */
  841.     char *p;
  842.     {
  843.     char far *q;
  844.     char far *r;
  845.  
  846.     if (!(q = r = (char *) _fmalloc( strlen( p ) + 1 )))
  847.         Nomem();
  848.     while (*r++ = *p++) ; /* copy string */
  849.     return( q );
  850.     }
  851.  
  852. static int same ( p, q ) /* return 1 if far strings are identical, else 0 */
  853.     char far *p;
  854.     char far *q;
  855.     {
  856.     while (*p && *p == *q) { /* compare bytes until mismatch or end */
  857.         p++;
  858.         q++;
  859.         }
  860.     return( (*p || *q) ? 0 : 1 );
  861.     }
  862.  
  863. void Report ( fout ) /* output routed board */
  864.     FILE *fout;
  865.     {
  866.     int r, c;
  867.     char b;
  868.     long x;
  869.  
  870.     printf( "enter Report()\n" );
  871.     /* output dimensions first */
  872.     b = (char)Nrows;    putc( b, fout );
  873.     b = (char)(Nrows>>8);    putc( b, fout );
  874.     b = (char)Ncols;    putc( b, fout );
  875.     b = (char)(Ncols>>8);    putc( b, fout );
  876.     /* now do rows and columns */
  877.     for (r = 0; r < Nrows; r++)
  878.         for (c = 0; c < Ncols; c++) {
  879.             x = GetCell( r, c, TOP ); /* first do frontside */
  880.             b = (char)x;        putc( b, fout );
  881.             b = (char)(x>>8);    putc( b, fout );
  882.             b = (char)(x>>16);    putc( b, fout );
  883.             b = (char)(x>>24);    putc( b, fout );
  884.             x = GetCell( r, c, BOTTOM ); /* then do backside */
  885.             b = (char)x;        putc( b, fout );
  886.             b = (char)(x>>8);    putc( b, fout );
  887.             b = (char)(x>>16);    putc( b, fout );
  888.             b = (char)(x>>24);    putc( b, fout );
  889.             }
  890.     printf( "leave Report()\n" );
  891.     }
  892.